package org.groovymud.object.room;

/* Copyright 2008 Matthew Corby-Eaglen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0 
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.groovymud.engine.event.EventScope;
import org.groovymud.engine.event.IScopedEvent;
import org.groovymud.object.AbstractContainer;
import org.groovymud.object.Container;
import org.groovymud.object.MudObject;
import org.groovymud.object.alive.Alive;
import org.groovymud.object.registry.InventoryHandler;
import org.groovymud.shell.telnetd.ExtendedTerminalIO;
import org.groovymud.utils.NumberToWordConverter;

public abstract class AbstractRoom extends AbstractContainer implements Room {

    private final static Logger logger = Logger.getLogger(AbstractRoom.class);

    private InventoryHandler exits;

    @Override
    public boolean checkCanAddItem(MudObject object) {
        return true;
    }

    public MudObject removeExit(AbstractExit object) {
        return removeItemFromInventoryHandler(object, getExits());
    }

    public void addExit(AbstractExit exit) {
        addItemToInventoryHandler(exit, getExits());
    }

    protected InventoryHandler getExits() {
        if (exits == null) {
            exits = new InventoryHandler();
        }
        return exits;
    }

    public AbstractExit getExit(String direction) {
        return (AbstractExit) getExits().getMudObject(direction);
    }

    public double getWeight() {
        return MudObject.CANNOT_PICK_UP;
    }

    public void setWeight(long weight) {
    }

    public void setExits(List<AbstractExit> exits) {
        Iterator exitIterator = exits.iterator();
        while (exitIterator.hasNext()) {
            addExit((AbstractExit) exitIterator.next());
        }
    }

    protected void writeLookHeader(ExtendedTerminalIO stream, Alive looker) throws IOException {
        stream.writeln(getName());
    }

    public void writeLookBody(ExtendedTerminalIO stream, Alive looker) throws IOException {
        stream.writeln(getDescription());
        if (getInventoryHandler().getMudObjectsMap(false).size() > 0) {
            stream.write("You see: ");
            super.writeLookBody(stream, looker);
            stream.writeln(".");
        }
        Map<Object, Set<MudObject>> alive = getInventoryHandler().getMudObjectsMap(true);

        String aliveContents = getContentsDescription(alive, looker, true);

        int aliveSize = getInventoryHandler().size(true) - 1;
        if (aliveSize > 0) {
            stream.write(aliveContents);
        }
        if (aliveSize > 0) {
            stream.writeln(aliveSize > 1 ? " are here." : " is here.");
        }
    }

    protected void writeLookFooter(ExtendedTerminalIO stream) {

        Set exits = getItemsFromInventoryHandler(getExits());
        try {
            stream.writeln("There " + (exits.size() == 1 && exits.size() != 0 ? "is" : "are") + " " + NumberToWordConverter.convert(exits.size(), false) + " exit" + (exits.size() == 1 ? "" : "s") + ":");
            Iterator iter = exits.iterator();
            int i = 0;
            while (iter.hasNext()) {
                AbstractExit exit = (AbstractExit) iter.next();
                stream.write(exit.getDirection() + (i < exits.size() - 1 ? ", " : "\r\n"));
                i++;
            }
        } catch (IOException e) {
            logger.error(e, e);
        }

    }

    @Override
    public void doEvent(IScopedEvent event) {
        // TODO Auto-generated method stub
        doEventInCollection(event, getExits().getMudObjects());
        super.doEvent(event);
    }

    @Override
    public boolean doCommand(String command, String argsAsString, MudObject performingObject) {
        boolean done = false;
        Set<MudObject> allContents = getItemsFromInventoryHandler(getExits());
        allContents.addAll(getItems());

        if (performingObject instanceof Container) {
            done = doCommandInContents(command, argsAsString, (Container) performingObject, allContents);
        }
        if (!done) {
            done = super.doCommand(command, argsAsString, performingObject);
        }
        return done;
    }

    public EventScope getScope() {
        return EventScope.ROOM_SCOPE;
    }
}
